package io.renren.common.utils.sftp;

import com.jcraft.jsch.SftpProgressMonitor;
import io.renren.common.utils.UuidUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DecimalFormat;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class FileProgressMonitor extends TimerTask implements SftpProgressMonitor {

    private Logger logger = LoggerFactory.getLogger(FileProgressMonitor.class);
    // 默认间隔时间为5秒
    private long progressInterval = 5 * 1000;

    private boolean isEnd = false; // 记录传输是否结束

    private long transfered; // 记录已传输的数据总大小

    private long fileSize; // 记录文件总大小

    private ScheduledThreadPoolExecutor scheduled; // 定时器对象

    private boolean isScheduled = false; // 记录是否已启动timer记时器

    private String uuid;  // 监视器编号

    //自定义的进度单例类(前端查询进度时，返回该对象)
    //有其他好的方法欢迎留言
    ScheduleSingLeTon insteans = ScheduleSingLeTon.getInsteans();

    // 初始化监视器
    public FileProgressMonitor(String fileName,long fileSize) {
        this.uuid = UuidUtil.getShortUUID();
        Map<String,Object> map = insteans.getFileMap();
        FileSingLeTon fileTon = new FileSingLeTon();
        fileTon.setEnd(false);
        fileTon.setFileName(fileName);
        fileTon.setFileSize(fileSize);
        map.put(this.uuid, fileTon);
    }

    @Override
    public void run() {
        if (!isEnd()) { // 判断传输是否已结束
            logger.info(this.uuid + ":Transfering is in progress.");
            long transfered = getTransfered();
            FileSingLeTon fileSingLeTon = (FileSingLeTon) insteans.getFileMap().get(this.uuid);
            if (transfered != fileSingLeTon.getFileSize()) { // 判断当前已传输数据大小是否等于文件总大小
                logger.info(fileSingLeTon.getFileName() + "  当前已传输数据大小: " + transfered + " bytes");
                sendProgressMessage(transfered);
            } else {
                logger.info(fileSingLeTon.getFileName()  + " 文件已传送完成.");
                setEnd(true); // 如果当前已传输数据大小等于文件总大小，说明已完成，设置end
            }
            insteans.getFileMap().put(this.uuid,fileSingLeTon);
        } else {
            logger.info("Transfering done. Cancel timer.");
            stop(); // 如果传输结束，停止timer记时器
            return;
        }
    }

    public void stop() {
        logger.info("Try to stop progress monitor.");
        if (scheduled != null) {
            scheduled.shutdownNow();
            scheduled = null;
            isScheduled = false;
        }
        logger.info("Progress monitor stoped.");
    }

    public void start() {
        logger.info("Try to start progress monitor.");
        if (scheduled == null) {
            scheduled = new ScheduledThreadPoolExecutor(1);
        }
        scheduled.scheduleAtFixedRate(this,0,1500, TimeUnit.MILLISECONDS);

        FileSingLeTon fileSingLeTon = (FileSingLeTon) insteans.getFileMap().get(this.uuid);
        fileSingLeTon.setPlan(0f);
        fileSingLeTon.setTransfered(0L);
        fileSingLeTon.setEnd(false);
        insteans.getFileMap().put(this.uuid,fileSingLeTon);
//        insteans.setTransfered(0L);
//        insteans.setPlan("0.00");
//        insteans.setEnd(false);
        isScheduled = true;
        logger.info("Progress monitor started.");
    }

    /**
     * 打印progress信息
     * @param transfered
     */
    private void sendProgressMessage(long transfered) {
        FileSingLeTon fileSingLeTon = (FileSingLeTon) insteans.getFileMap().get(this.uuid);
        if (fileSingLeTon.getFileSize() != 0) {
            double d = ((double)transfered * 100)/fileSingLeTon.getFileSize();
            DecimalFormat df = new DecimalFormat( "#.##");
            logger.info("Sending progress message: " + df.format(d) + "%");
            fileSingLeTon.setPlan(d);
            fileSingLeTon.setTransfered(transfered);
//            insteans.setPlan(df.format(d));
        } else {
            logger.info("Sending progress message: " + transfered);
        }
        insteans.getFileMap().put(this.uuid,fileSingLeTon);
    }

    /**
     * 实现了SftpProgressMonitor接口的count方法
     */
    @Override
    public boolean count(long count) {
        if (isEnd()){
            return false;
        }
        if (!isScheduled) {
            start();
        }
        add(count);
        return true;
    }

    /**
     * 实现了SftpProgressMonitor接口的end方法
     */
    @Override
    public void end() {
        FileSingLeTon fileSingLeTon = (FileSingLeTon) insteans.getFileMap().get(this.uuid);
        fileSingLeTon.setEnd(true);
        setEnd(true);
        insteans.getFileMap().put(this.uuid,fileSingLeTon);
//        insteans.setFileSize(0L);
//        insteans.setTransfered(0L);
//        insteans.setPlan("0.00");
        logger.info("transfering end.");
    }

    private synchronized void add(long count) {
        FileSingLeTon fileSingLeTon = (FileSingLeTon) insteans.getFileMap().get(this.uuid);
        fileSingLeTon.setTransfered(transfered + count);
        insteans.getFileMap().put(this.uuid,fileSingLeTon);
        transfered = transfered + count;
//        insteans.setTransfered(transfered);
    }

    private synchronized long getTransfered() {
        return transfered;
    }

    public synchronized void setTransfered(long transfered) {
        this.transfered = transfered;
    }

    public synchronized void setEnd(boolean isEnd) {
        this.isEnd = isEnd;
    }

    public synchronized boolean isEnd() {
        return isEnd;
    }

    public synchronized String getUuid() { return this.uuid;}

    public synchronized void setUuid(String uuid) { this.uuid = uuid;}

    @Override
    public void init(int op, String src, String dest, long max) {
        // Not used for putting InputStream
    }
}
